<html lang="zh">

<head>
	<title>少前芯片数据查询</title>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<link rel="icon" href="https://static.xuanxuan.tech/favicon.ico" type="image/x-icon" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/mini.css/3.0.1/mini-default.min.css" />
<script src="https://cdn.jsdelivr.net/npm/pako@1.0.10/dist/pako.min.js"></script>
<script>
	// from https://github.com/fc4soda/gfBadge/blob/master/src/index.js
	const encodeStr = (str) => {
		return encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
			function toSolidBytes(match, p1) {
				return String.fromCharCode('0x' + p1);
			});
	}
	const b64CharToByteArray = (byteCharacters, sliceSize = 512) => {
		const byteArrays = [];

		for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
			const slice = byteCharacters.slice(offset, offset + sliceSize);

			const byteNumbers = new Array(slice.length);
			for (let i = 0; i < slice.length; i++) {
				byteNumbers[i] = slice.charCodeAt(i);
			}

			const byteArray = new Uint8Array(byteNumbers);
			byteArrays.push(byteArray);
		}

		return byteArrays;
	}
	// from https://www.jianshu.com/p/0d5791718b52
	function handleCodePoints(array) {
		var CHUNK_SIZE = 0x8000; // arbitrary number here, not too small, not too big
		var index = 0;
		var length = array.length;
		var result = '';
		var slice;
		var arr = [];
		for (var i = 0, _i = array.length; i < _i; i++) {
			arr[i] = array[i];
		}
		while (index < length) {
			slice = arr.slice(index, Math.min(index + CHUNK_SIZE, length)); // `Math.min` is not really necessary here I think
			result += String.fromCharCode.apply(null, slice);
			index += CHUNK_SIZE;
		}
		return result;
	}

	function unzip(str) {
		var strData = window.atob(str);
		var charData = strData.split('').map(function (x) { return x.charCodeAt(0); });
		var binData = new Uint8Array(charData);
		var data = pako.inflate(binData);
		return handleCodePoints(data);
	}

	window.onload = function () {
		var hosts = 'https://codex.xuanxuan.tech:8080';

		let getPv = async function () {
			const pvUrl = 'https://www.fc4soda.moe/kis3/stats?view=count&url=gf.xuanxuan.tech/chip&format=json';
			const pvChartUrl = 'https://www.fc4soda.moe/kis3/stats?view=months&url=gf.xuanxuan.tech/chip&format=chart';
			try {
				const response = await fetch(pvUrl, {
					method: 'get'
				}).then(response => response.json())
					.then(function (json) {
						let pv = document.getElementById('pv');
						pv.text = json[0].second;
						pv.setAttribute('href', pvChartUrl);
						document.getElementById('pvSpan').style.display = 'inline';
					});
			} catch (err) {
				console.error(`Get visit number error: ${err}`);
			}
		}
		/** 如不需要访问统计请注释getPv调用 **/
		getPv()

		let getVal = function (selector) {
			return document.querySelector(selector);
		}

		let serialize = function (obj) {
			var str = [];
			for (var p in obj)
				if (obj.hasOwnProperty(p)) {
					str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
				}
			return str.join("&");
		}

		var saveData = (function () {
			var a = document.createElement("a");
			document.body.appendChild(a);
			a.style = "display: none";
			return function (byteArrays, contentType, fileName) {
				var blob = new Blob(byteArrays, { type: contentType }),
					url = window.URL.createObjectURL(blob);
				a.href = url;
				a.download = fileName;
				a.click();
				window.URL.revokeObjectURL(url);
			};
		}());

		let getReqData = function () {
			let uid = getVal('input[name="uid"]');
			let name = getVal('input[name="name"]');
			let locked = getVal('input[name="lock-status"]:checked');
			let equipped = getVal('input[name="equipped-status"]:checked');
			let reqData = {};
			reqData.uid = uid.value;
			reqData.name = name.value;
			reqData.locked = locked.value;
			reqData.equipped = equipped.value;
			return reqData;
		}

		document.getElementById('submit').addEventListener('click', async _ => {
			document.getElementById('msg').innerHTML = '正在查询……';
			try {
				var xhr = new XMLHttpRequest();
				xhr.open("POST", hosts + '/chip', true);
				xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
				xhr.send(serialize(getReqData()));

				xhr.onload = function () {
					document.getElementById('msg').innerHTML = '查询结束。';
					if (this.responseText[0] == '#') {
						var b64 = this.responseText.split('#');
						document.getElementById('chipResult').value = unzip(b64[1]);
					}
					else {
						document.getElementById('chipResult').value = this.responseText;
					}
				}
			} catch (err) {
				console.error(`Get chip data error: ${err}`);
			}
		});

		document.getElementById('export').addEventListener('click', async _ => {
			document.getElementById('msg').innerHTML = '正在查询……';
			try {
				var xhr = new XMLHttpRequest();
				xhr.open("POST", hosts + '/chipJson', true);
				xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
				xhr.send(serialize(getReqData()));

				xhr.onload = function () {
					document.getElementById('msg').innerHTML = '查询结束。';
					if (this.responseText[0] == '#') {
						var b64 = this.responseText.split('#');
						saveData(b64CharToByteArray(encodeStr(unzip(b64[1]))), 'application/json', 'chip.json');
					}
					else {
						document.getElementById('chipResult').value = this.responseText;
					}
				}
			} catch (err) {
				console.error(`Get chip data error: ${err}`);
			}
		});
	};
</script>
<style>
	#submit {
		margin: 1rem auto;
		display: block;
		padding: .3rem 2rem;
		font-size: 1.1rem;
	}

	#export {
		margin: 1rem auto;
		display: block;
		padding: .3rem 2rem;
		font-size: 1.1rem;
	}

	footer,
	h2 {
		text-align: center;
	}

	table {
		border-collapse: collapse;
	}

	#msg {
		color: #586e75;
	}

	input,
	textarea {
		width: 85%;
	}

	.responsive-label {
		align-items: center;
	}

	@media (min-width: 768px) {
		.responsive-label .col-md-3 {
			text-align: right
		}
	}

	footer {
		position: relative;
		margin-top: 3rem;
	}
</style>

<body>
	<h2>少前芯片数据查询</h2>
	<div class="container col-sm-12 col-md-8 col-lg-6">
		<form id="myForm" action="" method="POST">
			<fieldset>
				<div class="row responsive-label">
					<div class="col-sm-12 col-md-3">
						<label for="uid">UID</label>
					</div>
					<div class="col-sm-12 col-md">
						<input type="number" step=1 id="uid" name="uid" value="" required>
					</div>
				</div>
				<div class="row responsive-label">
					<div class="col-sm-12 col-md-3">
						<label for="name">昵称</label>
					</div>
					<div class="col-sm-12 col-md">
						<input type="text" id="name" name="name" value="" required>
					</div>
				</div>
				<div class="row responsive-label">
					<div class="col-sm-12 col-md-3">
						<label for="lock-status">输出芯片的<b>锁定</b>状态:</label>
					</div>
					<div class="col-sm-12 col-md">
						<input type="radio" name="lock-status" value=0 checked>任意
						<input type="radio" name="lock-status" value=1>已锁定
						<input type="radio" name="lock-status" value=2>未锁定
					</div>
				</div>
				<div class="row responsive-label">
					<div class="col-sm-12 col-md-3">
						<label for="lock-status">输出芯片的<b>装备</b>状态:</label>
					</div>
					<div class="col-sm-12 col-md">
						<input type="radio" name="equipped-status" value=0>任意
						<input type="radio" name="equipped-status" value=1>已装备
						<input type="radio" name="equipped-status" value=2 checked>未装备
					</div>
				</div>
				<div class="row">
					<div class="col-sm"></div>
					<div class="col-sm">
						<button type="button" class="shadowed" id="submit">查询</button>
					</div>
					<div class="col-sm">
						<button type="button" class="shadowed" id="export">导出</button>
					</div>
					<div class="col-sm"></div>
				</div>
				<div class="row responsive-label">
					<div class="col-sm-12 col-md-3">
						<label>芯片代码</label>
					</div>
					<div class="col-sm-12 col-md">
						<textarea autocomplete="off" id="chipResult" value=""></textarea>
					</div>
				</div>
			</fieldset>
		</form>
		<span id="msg"></span>
		<p><mark class="tertiary">说明</mark> 将手机连接任意WiFi，长按打开WiFi的高级设置，代理选择“自动代理”，代理地址为：</p>
		<pre>http://static.xuanxuan.tech/GF/GF.pac</pre>
		<p>然后重启游戏，登陆完成后在本页面填写UID和昵称并选择芯片配置，然后查询。
			<br>为避免滥用服务器，游戏只能进入基地界面并卡死，此时即可查询数据。若无此情况说明代理错误。
			<br>芯片代码请<code>Ctrl + A</code>全选复制。<b>数据有效期为10分钟。</b>
			<br>选择“导出”可以下载json文件，可供<a href="https://bbs.nga.cn/read.php?pid=349288968">自动录入工具</a>转换为<a
				href="https://bbs.nga.cn/read.php?tid=15287914">Excel版</a>。
			<br>台服需要下载安装<a href="http://static.xuanxuan.tech/GF/ca.crt">证书</a>。
			<br><b>本工具本身不会盗取账号也不会修改任何数据，但无法避免可能存在的服务器被攻击等风险，建议在使用前后修改密码！</b>
			<br><b>推荐：</b>CodeX重装芯片计算器，速度快方案多，可计算校准券消耗。<a href="https://bbs.nga.cn/read.php?tid=20284990">下载地址</a>
		</p>
	</div>

	<footer>
		<p><a href="/kalina">获取格林娜数据</a>
			| <a href="https://github.com/xxzl0130/GF_Tool_Server">GitHub</a>
			<span id="pvSpan" style="display: none;"> | 访问量: <a id="pv" href=""></a></span>
		</p>
	</footer>
	<!-- 如不需要访问统计请注释下方js -->
	<script src="https://www.fc4soda.moe/kis3/kis3.js"></script>
</body>

</html>